# coding=utf-8
import json
import sys
import time
from pdf2docx import Converter
import os


t02 = 0.2
t05 = 0.5
t1 = 1
t105 = 1.5
t2 = 2


def config_dirDOCXS():
    """
    检查并完善项目文件夹DOCXS：
    ./DOCXS: 输出word文档的存放目录
    :return: bool
    """
    if not os.path.exists('./DOCXS'):
        print('>>>Loading dir<./DOCXS>...')
        time.sleep(t02)
        os.mkdir('./DOCXS')
        return False
    return True


def config_dirPDFDOCS():
    """
    检查并完善项目文件夹PDFDOCS：
    ./PDFDOCS: 需要转化的PDF文件存放位置
    :return: bool
    """
    if not os.path.exists('./PDFDOCS'):
        print('>>>Loading dir<./PDFDOCS>...')
        time.sleep(t02)
        os.mkdir('./PDFDOCS')
        return False
    return True


def config_dirCONFIG():
    """
    检查并配置文件夹 ./CONFIG
    :return: bool
    """
    if not os.path.exists('./CONFIG'):
        print('>>>Loading dir<./CONFIG>...')
        time.sleep(t02)
        os.mkdir('./CONFIG')
        return False
    return True


def config_fileSETTINGS():
    """
    检查并完善配置文件 settings.json
    :return: bool
    """
    if not os.path.exists('./CONFIG/SETTINGS.JSON'):
        setting_dict = {
            "showInfo": 1,
            "coverageChange": 1,
            "autoUpdate": 1
        }
        print('>>>Loading file<./CONFIG/SETTINGS.JSON>...')
        time.sleep(t02)
        with open('./CONFIG/SETTINGS.json', 'w', encoding='utf-8')as f:
            json.dump(setting_dict, f)
            os.fsync(f.fileno())
        return False
    return True


def config_fileLOG(pdfPath='', docxPath='', timeData='', info='', func=''):
    """
    记录程序运行日志
    :param func: {
    "ReWrite": 清空日志,
    "OtherInfo": 追加操作信息,
    "ChangeInfo": 追加转化信息
    }
    :param info: 需要记录的操作信息
    :param timeData: 转化时的时间
    :param pdfPath: PDF路径
    :param docxPath: DOCX路径
    :return:
    """
    if func == "ReWrite":
        firstStartInfo = f"{info} | 时间:{timeData} | {int(time.time())}"
        print('>>>Loading file<./CONFIG/LOG.JSON>...')
        time.sleep(t02)
        with open('./CONFIG/LOG.txt', 'w', encoding='utf-8')as f:
            f.write(firstStartInfo + '\n')
            os.fsync(f.fileno())

    elif func == "OtherInfo":
        logInfo = f"{info} | 时间:{timeData} | {int(time.time())}"
        with open('./CONFIG/LOG.txt', 'a', encoding='utf-8')as f:
            f.write(logInfo + '\n')
            os.fsync(f.fileno())

    elif func == "ChangeInfo":
        logInfo = f"{info} | PDF位置:<{pdfPath}> | DOCX位置:<{docxPath}> | 时间:{timeData} | {int(time.time())}"
        with open('./CONFIG/LOG.txt', 'a', encoding='utf-8')as f:
            f.write(logInfo + '\n')
            os.fsync(f.fileno())


def get_timeData():
    """
    获取格式化时间
    :return: ****年-*月*日--*时:*分:*秒
    """
    timeData = time.strftime('%Y-%m-%d--%H:%M:%S')
    return timeData


def read_SETTINGS():
    """
    读取配置文件 SETTINGS.json
    :return: dict
    """
    with open('./CONFIG/SETTINGS.json', 'r', encoding='utf-8')as f:
        data = json.load(f)
    return data


def read_LOG(func=0):
    """
    读取LOG.txt中最后一行数据
    :param func: 读取LOG.txt的形式{0: "全部读取", 1: "读取第一条和最后一条记录"}
    :return:
    """
    with open('./CONFIG/LOG.txt', 'r', encoding='utf-8')as f:
        if func == 0:
            data = f.read()
            return data, 'OK'
        elif func == 1:
            first_line = f.readline()
            lines = f.readlines()
            return first_line, lines[-1]


def check_pdf():
    """
    获取./PDFDOCS中存放的pdf文件路径, 并将其以列表的形式储存
    :return: pdfPathList: 所有pdf文件路径列表
    """
    pdfDoc = os.listdir('./PDFDOCS')
    pdfPathList = []
    for i in pdfDoc:
        if i[-3:] == 'pdf' or i[-3:] == 'PDF':
            i = './PDFDOCS/' + i
            pdfPathList.append(i)
        else:
            continue
    return pdfPathList


def pdf_to_word(pdfPaths):
    """
    将pdf转化为word文档
    :param pdfPaths: pdf文件路径列表
    :return: None
    """
    for i, name in zip(pdfPaths, os.listdir('./PDFDOCS')):
        pdf_file = i
        docx_file = './DOCXS/' + name[:-3] + 'docx'
        print(f">>>正在转化<{pdf_file}>...")
        if os.path.exists(docx_file):
            data = read_SETTINGS()
            if data["coverageChange"]:
                print(f">>><{docx_file}>已存在--正在覆盖转化.")
                core_func(pdf_file, docx_file)
            else:
                print(f">>><{docx_file}>已存在--取消转化.")
                print('='*50)
                time.sleep(0.5)
                continue
        else:
            core_func(pdf_file, docx_file)
        os.system('cls' if os.name == 'nt' else 'clear')


def core_func(pdf_file, docx_file):
    """
    将pdf转化成docx的核心函数
    :param pdf_file: 待转化的pdf文件路径
    :param docx_file: 输出的word文档文件路径
    :return: None
    """
    cv = Converter(pdf_file)
    cv.convert(docx_file, start=0, end=None)
    cv.close()
    print(f">>>转化完成:{docx_file}--准备下一项", "\n", '=' * 50)
    timeData = get_timeData()
    config_fileLOG(pdf_file, docx_file, timeData, info='转化成功', func='ChangeInfo')
    time.sleep(2)


def info_show():
    """
    用于显示程序相关信息
    :return:
    """
    coverageChange = read_SETTINGS()["coverageChange"]
    if coverageChange:
        print("""=====程序使用须知=====
1.使用前请确保阅读过说明文档README.MD,若您还未阅读请关闭此窗口;
2.本程序转换的PDF文档中若存在浮动图片,转化效果可能不佳;
3.本程序基于gittee自动检测更新(测试版暂不支持自动更新,预计6.2日添加此功能);
4.本程序为测试版本,仅支持使用至2024.6.30 12:00;
5.前往gittee支持作者(给我一个star呗?)--> https://gitee.com/FlashVolador/pdf-to-word""")
        print('='*20)
        input('>>>ENTER TO START.')
    else:
        wellcomeInfo = "您好"
        if time.strftime('%p') == 'PM':
            wellcomeInfo = "下午好"
        elif time.strftime('%p') == 'AM':
            wellcomeInfo = "上午好"
        print(f">>>{wellcomeInfo},欢迎回来", time.strftime('%Y-%m-%d--%A'))
        time.sleep(t105)


def show_pdf(pdfPaths):
    """
    显示待转化的PDF文件路径
    :param pdfPaths:
    :return: True
    """
    print('='*5 + '待转化的PDF文件' + '='*5)
    for i in pdfPaths:
        print(i)
    print('='*25)
    return True


def clear_space():
    dirList = ['PDFDOCS', 'DOCXS', 'CONFIG']
    for d in dirList:
        d = './' + d  # d = './****'
        for i in os.listdir(f'{d}'):
            i = f'{d}/' + i
            print(f'>>>Deleting file<{i}>...')
            time.sleep(t05)
            os.remove(i)
        print(f'>>>Deleting dir<{d}>...')
        time.sleep(t05)
        os.rmdir(d)
    print('>>>Delete completely.')


def run():
    """
    组织函数代码
    :return: None
    """
    rec1 = config_dirDOCXS()
    rec2 = config_dirPDFDOCS()
    rec3 = config_dirCONFIG()
    rec4 = config_fileSETTINGS()

    if not os.path.exists('./CONFIG/LOG.txt'):
        firstStartInfo = f"初始化完成 | 时间:{get_timeData()} | {int(time.time())}"
        print('>>>Loading file<./CONFIG/LOG.JSON>...')
        time.sleep(t02)
        with open('./CONFIG/LOG.txt', 'w', encoding='utf-8')as f:
            f.write(firstStartInfo + '\n')
            os.fsync(f.fileno())

    if rec1 and rec2 and rec3 and rec4:
        config_fileLOG(timeData=get_timeData(), info='使用程序', func='OtherInfo')
        info_show()
        pdfPathList = check_pdf()
        check_update()
        while True:
            os.system('cls' if os.name == 'nt' else 'clear')
            print('-' * 10 + '功能列表' + '-' * 10)
            print('''1.开始转化.
2.设置.
3.查询历史记录.
4.清理日志.
5.卸载程序(这将清空PDFDOCS 和 DOCXS 内的所有文件!)''')
            funcChoice = input('>>>请选择功能(Q退出程序).')

            if funcChoice == '1':
                os.system('cls' if os.name == 'nt' else 'clear')
                show_pdf(pdfPathList)
                sureStart = input('>>>Enter确认开始转化(输"C"取消).')
                if sureStart == 'C' or sureStart == 'c':
                    continue
                else:
                    pdf_to_word(pdfPathList)
                    input('>>>转化结束.Enter返回功能页.')

            elif funcChoice == '2':
                a = True
                while a:
                    os.system('cls' if os.name == 'nt' else 'clear')
                    rec = setting()
                    if rec:
                        input('>>>设置完成.Enter返回功能页.')
                        a = False
                    else:
                        resetting = input('>>>设置无效!(R重新设置)')
                        if resetting == 'R' or resetting == 'r':
                            a = True
                        else:
                            a = False

            elif funcChoice == '4':
                os.system('cls' if os.name == 'nt' else 'clear')
                timeData = get_timeData()
                config_fileLOG(info='清理日志', timeData=timeData, func="ReWrite")
                input('>>>清理完成.Enter返回功能页.')

            elif funcChoice == '3':
                os.system('cls' if os.name == 'nt' else 'clear')
                record, message = read_LOG(func=0)
                print('='*10 + '历史记录' + '='*10)
                print(record, end='')
                print('='*28)
                input('>>>Enter返回功能页.')

            elif funcChoice == '5':
                os.system('cls' if os.name == 'nt' else 'clear')
                clear_space()
                input('>>>卸载完成.Enter退出程序.')
                sys.exit(0)

            elif funcChoice == 'Q' or funcChoice == 'q':
                sys.exit(0)

            else:
                print(">>>输入无效!")
                time.sleep(t05)

    else:
        config_fileLOG(timeData=get_timeData(), info='加载配置文件', func="OtherInfo")
        input('>>>初始化完成.请重启程序.')
        sys.exit(0)


def setting():
    """
    用于在程序内设置SETTINGS.JSON内容
    :return: bool
    """
    settingDict = read_SETTINGS()
    showInfo = settingDict["showInfo"]
    coverageChange = settingDict["coverageChange"]
    print('=' * 5 + '设置参数' + '=' * 5)
    print(f':param1: showInfo = <{settingDict["showInfo"]}> --是否显示程序使用须知(1显示 | 0不显示)')
    print(f':param2: coverageChange = <{settingDict["coverageChange"]}> --是否覆盖转化(1覆盖 | 0不覆盖 )')
    print(f':param3:  = <{settingDict["autoUpdate"]}> --几天进行一次更新检测(整数)')
    print('>>>请填写参数(无输入返回功能页):')
    settingList = ['0', '1']

    showInfo = input('>>>showInfo = ')
    if showInfo not in settingList:
        return False
    coverageChange = input('>>>coverageChange = ')
    if coverageChange not in settingList:
        return False
    autoUpdate = input('>>>autoUpdate = ')
    if not autoUpdate.isdigit() or int(autoUpdate) <= 0:
        return False

    showInfo = int(showInfo)
    coverageChange = int(coverageChange)
    setting_dict = {
        "showInfo": showInfo,
        "coverageChange": coverageChange,
        "autoUpdate": int(autoUpdate)
    }
    print('>>>Loading file<./CONFIG/SETTINGS.JSON>...')
    time.sleep(t02)
    with open('./CONFIG/SETTINGS.json', 'w', encoding='utf-8') as f:
        json.dump(setting_dict, f)
        os.fsync(f.fileno())
    config_fileLOG(timeData=get_timeData(), info=f'修改设置{setting_dict}', func="OtherInfo")
    return True


def check_update():
    """
    用于检查更新, 基于gittee(项目还未上线)
    :return:
    """
    firstLine, lastLine = read_LOG(func=1)
    firstLine = int(firstLine[-11:].strip())
    lastLine = int(lastLine[-11:].strip())
    settingDict = read_SETTINGS()
    autoUpdate = settingDict["autoUpdate"]
    timeDiffer = lastLine - firstLine
    if timeDiffer >= autoUpdate * 86400:
        # 检测更新的代码
        # 这个过一段时间再搞，最近太忙了，还要考试
        # 本来打算来一个急速开发的，结果还是搞了这么久，主要是人机交互这一块总是不满意，做UI界面又太费事了，没时间搞
        pass
    else:
        return True


def check_time_stamp():
    limitStamp = 1719720000
    currentStamp = time.time()
    if limitStamp > currentStamp:
        # dt = datetime.datetime.fromtimestamp(limitStamp)
        # now = datetime.datetime.now()
        # diff = dt - now
        # days = diff.days
        # hours, remainder = divmod(diff.seconds, 3600)
        # minutes, seconds = divmod(remainder, 60)
        # residual_time = f"{days}天{hours}小时{minutes}分钟{seconds}秒"
        return True
    else:
        return False


if __name__ == '__main__':
    stampCheck = check_time_stamp()
    if stampCheck:
        run()
    else:
        print('>>>程序过期!本版本仅支持使用至2024.6.30')
        input('>>>请前往gittee关注最新信息--> https://gitee.com/FlashVolador/pdf-to-word')
